package com.microservice.wechat.service.impl;

import com.google.common.util.concurrent.RateLimiter;
import com.microservice.wechat.client.WechatApiClient;
import com.microservice.wechat.dto.ArticleInfo;
import com.microservice.wechat.dto.ArticleViewData;
import com.microservice.wechat.entity.WechatArticle;
import com.microservice.wechat.mapper.WechatArticleMapper;
import com.microservice.wechat.service.ArticleViewSyncService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 文章阅读量同步服务实现
 */
@Slf4j
@Service
public class ArticleViewSyncServiceImpl implements ArticleViewSyncService {

    @Autowired
    private WechatApiClient wechatApiClient;

    @Autowired
    private WechatArticleMapper wechatArticleMapper;

    @Value("${wechat.sync.qps:4}")
    private double qps;

    @Value("${wechat.sync.batch-size:100}")
    private int batchSize;

    @Value("${wechat.sync.max-retry:2}")
    private int maxRetry;

    // 限流器：每秒最多允许的请求数
    private RateLimiter rateLimiter;

    @Override
    public void syncAllArticles() {
        log.info("==================== 开始同步文章阅读量 ====================");
        long startTime = System.currentTimeMillis();

        // 初始化限流器
        if (rateLimiter == null) {
            rateLimiter = RateLimiter.create(qps);
        }

        try {
            // 1. 调用API获取所有历史文章链接
            List<ArticleInfo> articleInfoList = wechatApiClient.getHistoryArticles();
            
            if (CollectionUtils.isEmpty(articleInfoList)) {
                log.warn("未获取到历史文章，同步结束");
                return;
            }

            log.info("获取到 {} 篇历史文章", articleInfoList.size());

            // 2. 逐个获取阅读量（受限流器控制）
            List<ArticleViewData> successList = new ArrayList<>();
            List<String> failedUrls = new ArrayList<>();

            for (ArticleInfo articleInfo : articleInfoList) {
                // 获取令牌（会阻塞直到获得）
                rateLimiter.acquire();

                ArticleViewData viewData = fetchViewCountWithRetry(articleInfo);
                if (viewData != null) {
                    successList.add(viewData);

                    // 每达到批量大小就批量更新一次
                    if (successList.size() >= batchSize) {
                        batchUpdateViewCount(successList);
                        log.info("已更新 {} 篇文章阅读量", successList.size());
                        successList.clear();
                    }
                } else {
                    failedUrls.add(articleInfo.getUrl());
                }
            }

            // 3. 更新剩余数据
            if (!successList.isEmpty()) {
                batchUpdateViewCount(successList);
                log.info("最后更新 {} 篇文章阅读量", successList.size());
            }

            // 4. 统计结果
            long duration = (System.currentTimeMillis() - startTime) / 1000;
            int successCount = articleInfoList.size() - failedUrls.size();
            log.info("==================== 文章阅读量同步完成 ====================");
            log.info("总耗时: {} 秒", duration);
            log.info("成功: {} 篇", successCount);
            log.info("失败: {} 篇", failedUrls.size());

            if (!failedUrls.isEmpty()) {
                log.warn("失败的文章URL: {}", failedUrls);
            }

        } catch (Exception e) {
            log.error("同步文章阅读量失败", e);
        }
    }

    /**
     * 获取单篇文章的阅读量（带重试）
     */
    private ArticleViewData fetchViewCountWithRetry(ArticleInfo articleInfo) {
        Exception lastException = null;

        for (int i = 0; i <= maxRetry; i++) {
            try {
                Integer viewCount = wechatApiClient.getArticleViewCount(articleInfo.getUrl());
                if (viewCount != null) {
                    return new ArticleViewData(articleInfo.getUrl(), articleInfo.getTitle(), viewCount);
                }
            } catch (Exception e) {
                lastException = e;
                log.warn("获取文章阅读量失败 [{}], 第 {} 次尝试: {}",
                        articleInfo.getTitle(), i + 1, e.getMessage());

                if (i < maxRetry) {
                    // 重试前等待（使用限流器）
                    rateLimiter.acquire();
                }
            }
        }

        log.error("获取文章阅读量最终失败: {}", articleInfo.getUrl(), lastException);
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateViewCount(List<ArticleViewData> viewDataList) {
        if (CollectionUtils.isEmpty(viewDataList)) {
            return;
        }

        try {
            // 转换为WechatArticle实体
            List<WechatArticle> articles = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();

            for (ArticleViewData data : viewDataList) {
                WechatArticle article = new WechatArticle();
                article.setArticleUrl(data.getUrl());
                article.setTitle(data.getTitle());
                article.setViewCount(data.getViewCount());
                article.setLastSyncTime(now);
                article.setSyncStatus(1); // 1-同步成功
                articles.add(article);
            }

            // 批量插入或更新
            int count = wechatArticleMapper.batchInsertOrUpdate(articles);
            log.debug("批量更新文章阅读量，影响行数: {}", count);

        } catch (Exception e) {
            log.error("批量更新文章阅读量失败", e);
            throw e;
        }
    }
}
